#include "../head/client.h"

// 发送数据给服务器
int send_str(int socket_fd, void *buf)
{
	train_t train;
	bzero(&train, sizeof(train));
	char *p = (char *)buf;
	train.length = strlen(p);
	memcpy(train.data, p, train.length);
	send(socket_fd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
	return 0;
}

// 接收来自服务器的数据
int recvn(int socket_fd, void *buf, int length)
{
	int total = 0; // 已经接收的长度
	char *p = (char *)buf;
	while (total < length)
	{
		ssize_t sret = recv(socket_fd, p + total, length - total, 0);
		total += sret;
	}
	return 0;
}

// 发送文件给服务器
int send_file(int socket_fd, int file_fd)
{
	train_t train;
	bzero(&train, sizeof(train));
	struct stat statbuf;
	bzero(&statbuf, sizeof(statbuf));
	fstat(file_fd, &statbuf);

	// 先发送文件长度
	/* train.length = sizeof(statbuf.st_size);
	memcpy(train.data, &statbuf.st_size, train.length);
	send(socket_fd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL); */
	send(socket_fd, &statbuf.st_size, sizeof(off_t), MSG_NOSIGNAL);

	// 根据文件长度选择不同的文件发送方式
	if (statbuf.st_size >= BIG_FILE) // 大文件
	{
		sendfile(socket_fd, file_fd, NULL, statbuf.st_size);
	}
	else // 小文件
	{
		while (1)
		{
			ssize_t read_ret = read(file_fd, train.data, sizeof(train.data));
			if (read_ret == 0)
			{
				break;
			}
			train.length = read_ret;
			send(socket_fd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
		}
	}
	// 发送长度为0的train代表数据发送完毕
	train.length = 0;
	send(socket_fd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);

	return 0;
}

int recv_file(int socket_fd, int file_fd)
{
	train_t train;
	bzero(&train, sizeof(train));

	struct stat cur_st;
	fstat(file_fd, &cur_st);
	off_t cur_size = cur_st.st_size;

	// 接收服务端即将发送过来的文件的大小（剩余文件的大小）
	off_t file_size = 0;
	bzero(&train, sizeof(train));
	recv(socket_fd, &file_size, sizeof(off_t), MSG_WAITALL);
	printf("文件大小：%ld\n", file_size);

	if (file_size >= BIG_FILE)
	{
		ftruncate(file_fd, file_size + cur_size);
		char *p = (char *)mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_fd, 0);
		ERROR_CHECK(p, MAP_FAILED, "mmap");
		recv(socket_fd, p, file_size, MSG_WAITALL);
		munmap(p, file_size);
	}
	else
	{
		while (1)
		{
			recv(socket_fd, &train.length, sizeof(train.length), MSG_WAITALL);
			if (train.length == 0)
			{
				break;
			}
			recv(socket_fd, train.data, train.length, MSG_WAITALL);
			write(file_fd, train.data, train.length);
		}
	}
	printf("100.00%%\n");
	return 0;
}